package provisioning.ranjan;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.amazonaws.services.autoscaling.model.AutoScalingGroup;
import com.amazonaws.services.cloudwatch.AmazonCloudWatch;
import com.amazonaws.services.cloudwatch.model.Datapoint;
import com.amazonaws.services.cloudwatch.model.Dimension;
import com.amazonaws.services.cloudwatch.model.GetMetricStatisticsRequest;
import com.amazonaws.services.cloudwatch.model.GetMetricStatisticsResult;
import commons.client.Scheduler;
import commons.client.UserModel;
import commons.monitor.CloudWatchReceiver;

/**
 * This is a data collector used in the implementation of Ranjan. 
 * @author Lilia Rodrigues Sampaio - liliars@lsd.com.br
 *
 */
public class RanjanCollector {
	
	private AmazonCloudWatch monitor;
	private UserModel client;
	private static int CURRENT_NUMBER_OF_MACHINES;	
	public static final double TARGET_UTILIZATION = 0.75; 

	/**
	 * Default constructor
	 * @param client The client of application
	 */
	public RanjanCollector(UserModel client) {
		monitor = CloudWatchReceiver.getMonitor();
		this.client = client;
		
		Scheduler.getScheduler().groupsInitialization(client.getConfigName(), client.getInstanceType(), client);
	}

	/**
	 * The number of complete requests in the last interval
	 * @return the number of complete requests
	 * 
	 * TODO Find a way to recover this information from the monitor. 
	 * If it doesn't possible, let this job for the own monitor of the application.  
	 */
	public double numberOfCompleteRequests() {
		return 0;
	}
	
	/**
	 * The number of arrivals requests in the last interval
	 * @return the number of arrivals
	 */
	public double numberOfArrivals(Date start, Date end, String groupName) {
		GetMetricStatisticsRequest request = new GetMetricStatisticsRequest()
		.withStartTime(start).withEndTime(end)
		
		.withDimensions(new Dimension().withName(groupName))
		.withMetricName("RequestCount").withStatistics("Sum");
		
		GetMetricStatisticsResult getMetricStatisticsResult = monitor.getMetricStatistics(request);
		double sumArrivals = 0;
		
		@SuppressWarnings("rawtypes")
		List dataPoints = getMetricStatisticsResult.getDatapoints();
		for (Object dataPoint : dataPoints) {
			Datapoint dp = (Datapoint) dataPoint;
			sumArrivals += dp.getSum();
		}
		
		return sumArrivals;
	}
	
	/**
	 * The mean of CPU utilization from all the machines in use
	 * @return the mean of CPU utilization
	 * 
	 * TODO See how get the intervals for the consult.
	 */
	public List<Double> averageCPUUtilizationForAGroup(Date start, Date end, String groupName) {
		GetMetricStatisticsRequest request = new GetMetricStatisticsRequest()
		.withStartTime(start).withEndTime(end)
		
		.withDimensions(new Dimension().withName(groupName))
		.withMetricName("CPUUtilization").withStatistics("Average");
		
		GetMetricStatisticsResult getMetricStatisticsResult = monitor.getMetricStatistics(request);
		List<Double> avgCPUUtilization = new ArrayList<Double>();
		
		@SuppressWarnings("rawtypes")
		List dataPoints = getMetricStatisticsResult.getDatapoints();
		for (Object dataPoint : dataPoints) {
			Datapoint dp = (Datapoint) dataPoint;
			avgCPUUtilization.add(dp.getAverage());
		}
		
		return avgCPUUtilization;
	}
	
	/**
	 * The number of current servers on the application. This number should be recovered from 
	 * each auto scaling group
	 * @return the number of current servers
	 */
	public int numberOfCurrentServers() {
		CURRENT_NUMBER_OF_MACHINES = 0;
		
		for(AutoScalingGroup group : client.getGroups()) {
			CURRENT_NUMBER_OF_MACHINES += group.getInstances().size();
		}
		return CURRENT_NUMBER_OF_MACHINES;
	}
	
}
